#include <database.h>

#include <stdlib.h>
#include <iostream>
#include <QtCore>


using namespace std;

Database::Database()
{
    this->db = QSqlDatabase::addDatabase("QPSQL");
    this->connect();
}

//Destruktor
Database::~Database()
{
    //Nothing at the moment;
}


bool Database::connect() {
    this->db.setHostName("localhost");
    this->db.setDatabaseName("SE-DB");
    this->db.setUserName("postgres");
    this->db.setPassword("post");
    if (!this->db.open()) {
        fail("open database");
        return false;
    } else
        return true;
}

bool Database::disconnect() {
    if(db.isOpen()) {
        db.close();
        return true;
    } else {
        return false;
    }
}

bool Database::createTables() {

    if(!query.exec("Create Table D_dancer( "
                    "dancer_id SERIALPRIMARYKEY,"
                    "first_name VARCHAR NOT NULL,"
                    "last_name VARCHAR NOT NULL,"
                    "gender CHAR NOT NULL,"
                    "date_of_birth VARCHAR,"
                    "postal_code VARCHAR,"
                    "location VARCHAR,"
                    "street_name VARCHAR,"
                    "house_number VARCHAR,"
                    "CONSTRAINT name_constraint UNIQUE (first_name, last_name)"
                    ");"))
            return false;

    if(!query.exec("CREATE TABLE D_user ("
                   "user_id SERIAL PRIMARY KEY,"
                   "password VARCHAR NOT NULL,"
                   "is_admin BOOLEAN DEFAULT FALSE"
                    ");"))
            return false;

    if(!query.exec("CREATE TABLE D_prioritylist ("
                   "dancer_id_a INTEGER,"
                   "dancer_id_b INTEGER,"
                   "priority INTEGER DEFAULT 0,"
                   "CONSTRAINT primary_key_constraint PRIMARY KEY (dancer_id_a, dancer_id_b),"
                   "FOREIGN KEY dancer_id_a REFERENCES D_dancer (dancer_id) ON DELETE CASCADE,"
                   "FOREIGN KEY dancer_id_b REFERENCES D_dancer (dancer_id) ON DELETE CASCADE,"
                   "CHECK (dancer_id_a != dancer_id_b)"
                   ");"))
            return false;
}

bool Database::dropTables() {

    if(!query.exec("DROP TABLE D_dancer;"
                        "DROP TABLE D_user;"
                            "DROP TABLE D_prioritylist;"))
        return false;
}

bool Database::selectUser(int user_id, QString password) {

    query.prepare("SELECT count(*) FROM D_user WHERE user_id = :user_id AND password = :password");
    query.bindValue("user_id", user_id); // prepared Statement, prevent sql injections
    query.bindValue("password", password);
    if(!query.exec()) {
        fail("Select User");
        return false;
    }
    return true;
}

bool Database::setAdmin(QString password1, QString password2) {

    query.prepare("INSERT INTO D_user (password, is_admin)"
                    "VALUES (:password, :is_admin)");
    query.bindValue(":password", password1);
    query.bindValue(":is_admin", true);

    if (password1.toStdString() == password2.toStdString()) {
        if(!query.exec()) {
            Database::fail("Insert Admin");
            return false;
        }
        return true;
    }
}

bool Database::setUser(QString password1, QString password2) {

    query.prepare("INSERT INTO D_user (password, is_admin)"
                    "VALUES (:password, DEFAULT)");
    query.bindValue(":password", password1);

    if (password1.toStdString() == password2.toStdString()) {
        if(!query.exec()) {
            fail("Insert User");
            return false;
        }
        return true;
    }
}

// Fehlermeldung ausgeben und Programm beenden.
void Database::fail (QString what) {
    // Da ein QString nicht mittels << ausgegeben werden kann,
    // muss er mittels toStdString in einen std::string umgewandelt werden.
    cout << what.toStdString() << " failed" << endl;
    exit(1);
}













